<template>
	<view class="org">
		<view v-show="!switchOrgSearch">
			<!-- 上方搜索栏入口 -->
			<view style="margin-bottom: 10rpx; margin-right: 20rpx">
				<u-search
					placeholder="搜索"
					shape="square"
					:show-action="uSearchOptions.showAction"
					:input-align="uSearchOptions.inputAlign"
					height="70"
					:disabled="true" 
					@click="toShowOrgSearch"
				></u-search>
			</view>
			<!-- 下方内容显示区 -->
			<view class="org-content">
				<!--  面包屑导航 -->
				<view class="org-content__current">
					<!-- 导航区 -->
					<view class="org-content__current__nav">
						<text @click="handleCurrentListClick(-1)" :class="{not_the_last_text:isNotLastNavTextNode(-1)}">{{ currentFixedNavTitle }}</text>
						<text v-for="(item, index) in currentData" 
							:key="index" 
							:class="{not_the_last_text:isNotLastNavTextNode(index)}" 
							@click="handleCurrentListClick(index)" 
						>
							<text style="margin-left: 10rpx; margin-right: 10rpx">/</text>
							{{ item[label] }}
						</text>
					</view>
					<slot name="switch-show-type-btn" :showType="showType">
						<!-- 切换按钮 -->
						<view class="org-content__current__switchBtn">
							<!-- 组织/标签  切换 -->
							<button @click="switchShowType" size="default" type="default" class="btn">
								<text style="font-weight: bold">
									{{ showType == 'org' ? orgText : tagText }}
								</text>
							</button>
						</view>
					</slot>
				</view>
				<!-- 内容显示区 -->
				<view class="org-content__warp">
					<view class="org-content__ul">
						<template v-if="renderData.length > 0">
							<slot name="content-area" :renderData="renderData">
								<view class="org-content__item" v-for="item in renderData" :key="item[nodeKey]">
									<!-- 复选框 -->
									<checkbox v-if="selectTypes.includes(item[nodeType])" @click="handleItemClick(item)" :checked="isChecked(item)"></checkbox>
									<!-- 图标 -->
									<image
										v-if="isShowIcon"
										@click="handleItemClick(item)"
										class="avatar"
										:style="{
											visibility: item[icon] || defaultIcon ? 'visible' : 'hidden'
										}"
										src="item[icon] || defaultIcon"
									></image>
									<!--  名称显示 -->
									<text class="org-content__item-text" @click="handleItemClick(item)">
										{{ item[label] }}
									</text>
									<!-- 下级按钮 -->
									<text v-if="item.hasChildren" @click="handleItemChildClick(item)" class="org-content__item-child">></text>
								</view>
							</slot>
						</template>
						<!-- 无数据提示:两种：1.数据源压根儿没数据 2.搜索结果没数据 -->
						<template v-else>
							<slot name="empty-tips">
								<view class="empty">
									暂无{{ showType == 'org' ? `与 '${orgText}' 相关` : `与 '${tagText}' 相关` }}数据
								</view>
							</slot>
						</template>
					</view>
				</view>
			</view>
		</view>
		<view v-if="switchOrgSearch">
			<js-org-search 
				:label="label" 
				:node-key="nodeKey" 
				:node-type="nodeType"  
				:is-show-icon="isShowIcon" 
				:default-icon="defaultIcon" 
				:icon="icon" 
				@on-org-search-close="onOrgSearchClose" 
				@on-org-search-select="onOrgSearchSelect" 
				@on-org-search-expand="onOrgSearchExpand"
			></js-org-search>
		</view>
		<!-- 已选择列表分栏 -->
		<view class="org-content__operation">
			<!-- 已选择项目 -->
			<slot name="selected-list" :selectedItems="selectedItems">
				<!--  已选择的项目列表 -->
				<view class="selected-item-list">
					<text class="seleted-item" v-for="(item, index) in selectedItems" :key="index">
						{{ item[label] }}
						<i @click="delItem(item)" class="close-icon"></i>
					</text>
				</view>
			</slot>
			<!-- 已选数量及操作区 -->
			<view class="result-display">
				<slot name="result-area" :selectedItems="selectedItems">
					<view class="result-area__display">
						<text v-if="!selectedItems.length">暂无选择</text>
						<text v-if="selectedItems.length">已选择 {{ selectedItems.length }} 项</text>
					</view>
					<view class="result-area__operation">
						<text class="cancel-btn" @click="handleCancel">{{ cancelText }}</text>
						<text @click="handleSubmit" class="submit-btn">{{ submitText }}</text>
					</view>
				</slot>
			</view>
		</view>
	</view>
</template>
<script>
import JsOrgSearch from '@/components/js-org/js-org-search.vue'	
export default {
	name: 'JsOrg',
	components: {
		JsOrgSearch
	},
	props: {
		data: {
			type: Array,
			default: () => []
		},
		// 可操作类型（控制是否可点击、展示复选框等）
		selectTypes: {
			type: Array,
			// 组织(org)：1 、用户(user)：2 、标签(tag)：3
			default: () => ['1', '2', '3']
		},
		defaultIcon: {
			type: String,
			default: ''
		},
		label: {
			type: String,
			default: 'name'
		},
		nodeKey: {
			type: String,
			default: 'id'
		},
		nodeType: {
			type: String,
			default: 'type'
		},
		// 是否需要联合主键（为true则表示需要nodeKey与nodeType共同来表示对象的唯一键）
		needCompositeKey: {
			type: Boolean,
			default: false
		},
		children: {
			type: String,
			default: 'children'
		},
		icon: {
			type: String,
			default: 'avatar'
		},
		isShowClearBtn: {
			type: Boolean,
			default: true
		},
		searchPlaceholder: {
			type: String,
			default: '搜索'
		},
		submitText: {
			type: String,
			default: '确定'
		},
		cancelText: {
			type: String,
			default: '关闭'
		},
		isShowIcon: {
			type: Boolean,
			default: false
		},
		isMultiple: {
			type: Boolean,
			default: true
		},
		isSelectRequired: {
			type: Boolean,
			default: false
		},
		selectedList: {
			type: Array,
			default: () => []
		},
		slideDistance: {
			type: Number,
			default: 100
		},
		// 默认展示类型，目前支持org(组织)、tag(标签)
		defaultShowType: {
			type: String,
			default: 'org'
		},
		orgText: {
			type: String,
			default: '组织'
		},
		tagText: {
			type: String,
			default: '标签'
		},
		fixedNavTitle: {
			type: String,
			default: '可选范围 ~ 组织'
		}
	},
	// 提供给后代组件的数据/方法
	provide(){
		return {
			p_isChecked: this.isChecked
		}
	},
	data() {
		return {
			// 当前数据，用于存储已下钻的目录节点，用于展示导航条
			currentData: [],
			// 已选择的数据集合
			selectedItems: [],
			// 用来渲染的数据源
			renderData: [],
			showType: '',
			currentFixedNavTitle: '',
			constFixedNavTitleOrg: '可选范围 ~ 组织',
			constFixedNavTitleTag: '可选范围 ~ 标签',
			uSearchOptions: {
				showAction: false,
				inputAlign: 'center'
			},
			switchOrgSearch: false
		};
	},
	watch: {
		// 监听父组件传来的defaultShowType的值
		defaultShowType: {
			handler(newVal, oldVal) {
				this.showType = newVal;
			},
			deep: true,
			immediate: true
		},
		// 监听父组件传来的值
		data: {
			handler(val) {
				this.renderData = val;
			},
			immediate: true
		}
	},
	mounted() {
		if (Array.isArray(this.selectedList) && this.selectedList.length > 0) {
			this.selectedItems = this.selectedList;
		}
		this.renderData = this.data;
		if(this.defaultShowType === 'org') {
			this.currentFixedNavTitle = this.constFixedNavTitleOrg;
		}else if(this.defaultShowType === 'tag') {
			this.currentFixedNavTitle = this.constFixedNavTitleTag;
		}
	},

	methods: {
		/**
		 * 切换组织/标签
		 */
		switchShowType() {
			switch (this.showType) {
				case 'org':
					this.showType = 'tag';
					this.currentData = [];
					this.currentFixedNavTitle = this.constFixedNavTitleTag;
					break;
				case 'tag':
					this.showType = 'org';
					this.currentData = [];
					this.currentFixedNavTitle = this.constFixedNavTitleOrg;
				default:
					break;
			}
			this.$emit('on-switch-show-type', this.showType);
		},

		/**
		 * 判断是否显示选中状态
		 * @param {Object} data
		 */
		isChecked(data) {
			let checked = this.selectedItems.some((item) => {
				if (this.needCompositeKey) {
					return item[this.nodeKey] == data[this.nodeKey] && item[this.nodeType] == data[this.nodeType];
				} else {
					return item[this.nodeKey] == data[this.nodeKey];
				}
			});
			return checked;
		},

		/**
		 * 点击选项
		 * @param {Object} row
		 */
		handleItemClick(row) {
			if (!this.selectTypes.includes(row[this.nodeType])) {
				return;
			}
			// 多选
			if (this.isMultiple) {
				const data = JSON.parse(JSON.stringify(row));
				let isExist = this.selectedItems.some((i) => {
					if (this.needCompositeKey) {
						return data[this.nodeKey] == i[this.nodeKey] && data[this.nodeType] == i[this.nodeType];
					} else {
						return data[this.nodeKey] == i[this.nodeKey];
					}
				});
				if (isExist) {
					// 存在当前项，则取消选择
					this.selectedItems = this.selectedItems.filter((res) => {
						if (this.needCompositeKey) {
							return res[this.nodeKey] !== data[this.nodeKey] || res[this.nodeType] !== data[this.nodeType];
						} else {
							return res[this.nodeKey] !== data[this.nodeKey];
						}
					});
				} else {
					// 不存在当前项，则将其加入到所选列表中
					this.selectedItems.push(data);
				}
			} else {
				// 单选
				this.selectedItems = [];
				this.selectedItems.push(row);
			}
			this.$emit('on-select', row);
		},

		/**
		 * 点击下级按钮获取下级目录及人员
		 * @param {Object} row
		 */
		handleItemChildClick(row) {
			this.currentData.push(row);
			this.$emit('on-expand', row);
		},

		/**
		 * 点击面包屑导航触发
		 * @param {Object} index
		 */
		handleCurrentListClick(index) {
			// 如果点击当前项(也就是最后一个导航节点时)，则不做任何操作
			if (index == this.currentData.length - 1 || (this.currentData.length === 0 && index == -1)) {
				return;
			}
			// 处理导航栏数据
			if (index > -1) {
				this.currentData = this.currentData.slice(0, index + 1);
				this.$emit('on-nav', this.currentData[index]);
			} else {
				// 如果当前就是全部则不做任何操作
				this.currentData = [];
				this.$emit('on-nav', '-1');
			}
		},
		/**
		 * 判断节点是否不是最后一个导航节点
		 */
		isNotLastNavTextNode(index) {
			let isLast = false;
			if(index === -1 && this.currentData.length == 0){
				isLast = true;
			}
			if(index > -1 && index === (this.currentData.length - 1)) {
				isLast = true;
			}
			return !isLast;
		},

		/**
		 * 删除已选列表中的item
		 * @param {Object} data
		 */
		delItem(data) {
			this.selectedItems = this.selectedItems.filter((item) => {
				if (this.needCompositeKey) {
					return item[this.nodeKey] !== data[this.nodeKey] || item[this.nodeType] !== data[this.nodeType];
				} else {
					return item[this.nodeKey] !== data[this.nodeKey];
				}
			});
		},

		/**
		 * 确定提交
		 */
		handleSubmit() {
			if (this.isSelectRequired && !this.selectedItems.length) {
				this.$u.toast('未做任何选择，请选择后重试');
				return;
			}
			// 触发父组件绑定事件，将值传回去
			this.$emit('on-submit', this.selectedItems);
		},

		/**
		 * 取消
		 */
		handleCancel() {
			this.$emit('on-cancel');
		},
		
		/**
		 * 切换展示搜索页组件
		 */
		toShowOrgSearch() {
			this.switchOrgSearch = !this.switchOrgSearch;
		},
		
		// 以下是监听js-org-search组件事件的回调函数
		
		/**
		 * 切换关闭搜索页组件
		 */
		onOrgSearchClose() {
			this.switchOrgSearch = false;
		},
		onOrgSearchSelect(data) {
			this.handleItemClick(data);
		},
		onOrgSearchExpand(data) {
			this.handleItemChildClick(data);
			this.onOrgSearchClose();
		}
	}
};
</script>
<style scoped>
.org {
	position: absolute;
	inset: 20rpx;
	padding: 30rpx;
}

.org-content * {
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: 28rpx;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

.org-content {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border: 2rpx solid #eee;
}

.org-content .org-content__current {
	display: flex;
	word-break: keep-all;
	font-size: 28rpx;
	height: 100%;
	padding: 10rpx;
	align-items: center;
	box-shadow: 0rpx 0rpx 4rpx 4rpx #eee;
	overflow-x: auto;
	overflow-y: hidden;
	justify-content: space-between;
}

.org-content .org-content__current .org-content__current__nav .not_the_last_text {
	color: #0000ff;
}

/* switch org/tag button style */
.org-content .org-content__current .org-content__current__switchBtn .btn {
	border: 1rpx solid #5284ea;
	border-radius: 10rpx;
	padding: 0 10rpx;
	background: #fff;
	color: #5284ea;
}

.org-content .org-content__warp {
	flex: 1;
	overflow-y: auto;
	border-top: 2rpx solid #eee;
}

.org-content .org-content__warp .empty {
	padding: 40rpx 0;
	color: #999;
	text-align: center;
}

.org-content .org-content__warp .org-content__ul {
	height: calc(100vh - 17rem);
	overflow: auto;
}
.org-content .org-content__warp .org-content__item {
	border-bottom: 2rpx solid #eee;
	height: 76rpx;
	margin: 0 20rpx;
	display: flex;
	align-items: center;
	padding: 16rpx 0;
	box-sizing: border-box;
}

.org-content .org-content__warp .org-content__item:last-child {
	border: none;
}

.org-content .org-content__warp .org-content__item:first-child {
	border-top: none;
}

.org-content .org-content__warp .org-content__item .avatar {
	width: 50rpx;
	height: 50rpx;
	border-radius: 50%;
	object-fit: cover;
	margin-right: 10rpx;
}

.org-content .org-content__warp .org-content__item .org-content__item-text {
	flex: 1;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.org-content .org-content__warp .org-content__item .org-content__item-count {
	width: 90rpx;
	padding-right: 10rpx;
	text-align: center;
	color: #999;
}

.org-content .org-content__warp .org-content__item .org-content__item-child {
	padding: 0 8px;
	width: max-content;
	color: #409eff;
	border-left: 2rpx solid #eee;
	box-sizing: border-box;
	cursor: pointer;
	font-weight: 600;
}

.org-content__operation {
	position: absolute;
	bottom: 0;
	left: 20rpx;
	right: 20rpx;
}

.org-content__operation .result-display {
	display: flex;
	justify-content: space-between;
	padding: 0.5rem 0;
	border-top: 2rpx solid rgb(247, 236, 236);
}

.org-content__operation .result-display .result-area__operation .cancel-btn {
	width: 80rpx;
	margin-right: 20rpx;
	padding: 0;
	color: #3c6eb7;
	text-align: center;
	font-size: 40rpx;
}

.org-content__operation .result-display .result-area__operation .submit-btn {
	width: 80rpx;
	padding: 0;
	color: #3c6eb7;
	text-align: center;
	font-size: 40rpx;
}

.selected-item-list {
	height: 4rem;
	overflow: auto;
}

.seleted-item {
	background-color: #ecf5ff;
	display: inline-block;
	padding: 0 10rpx;
	line-height: 1.3rem;
	font-size: 30rpx;
	color: #409eff;
	border: 2rpx solid #d9ecff;
	border-radius: 8rpx;
	box-sizing: border-box;
	white-space: nowrap;
	margin: 10rpx;
}

.close-icon:before {
	content: '\2716';
	font-size: xx-small;
	font-style: normal;
	opacity: 0.5;
}
</style>
